﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Brain.Rendering;

namespace Brain.Editor
{
#if WINDOWS || XBOX
    public class PickingManager3D_Color : IPickingManager3D
    {
        /// <summary>
        /// The Last color a IPickedObject was assigned
        /// </summary>
        protected Color LastPickColor = new Color(0, 0, 0);
        
        public IPickedObject SelectedWorldObject { get; set; }

        public bool Manipulating { get; set; }

        public ManipulationMode3D Mode { get; set; }

        public bool ShouldUpdate { get; set; }
        public bool ShouldDraw { get; set; }

        public int Grid { get; protected set; }

        public event SetIPickerObject OnSelected;

        public float ScaleBefore;
        public Vector3 UnitAxis;

        #region Resources
#if WINDOWS
        private Byte[] pickingEffectCode = new Byte[1620] {207,11,240,188,16,0,0,0,0,0,0,0,0,0,0,0,1,9,255,254,192,1,0,0,0,0,0,0,3,0,0,0,2,0,0,0,96,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,87,111,114,108,100,0,122,0,3,0,0,0,2,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,86,105,101,119,0,0,0,0,3,0,0,0,2,0,0,0,48,1,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,80,114,111,106,101,99,116,105,111,110,0,0,3,0,0,0,1,0,0,0,104,1,0,0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,67,111,108,111,114,0,0,0,1,0,0,0,16,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,15,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,80,97,115,115,49,0,0,0,11,0,0,0,84,101,99,104,110,105,113,117,101,49,0,0,4,0,0,0,1,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,108,0,0,0,136,0,0,0,0,0,0,0,0,0,0,0,212,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,64,1,0,0,92,1,0,0,0,0,0,0,0,0,0,0,176,1,0,0,0,0,0,0,1,0,0,0,164,1,0,0,0,0,0,0,2,0,0,0,146,0,0,0,0,0,0,0,120,1,0,0,116,1,0,0,147,0,0,0,0,0,0,0,144,1,0,0,140,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,1,0,0,0,0,0,0,0,232,1,0,0,0,2,255,255,254,255,22,0,67,84,65,66,28,0,0,0,35,0,0,0,0,2,255,255,0,0,0,0,0,0,0,0,0,0,0,32,28,0,0,0,112,115,95,50,95,48,0,77,105,99,114,111,115,111,102,116,32,40,82,41,32,72,76,83,76,32,83,104,97,100,101,114,32,67,111,109,112,105,108,101,114,32,57,46,50,54,46,57,53,50,46,50,56,52,52,0,254,255,93,0,80,82,69,83,1,2,88,70,254,255,36,0,67,84,65,66,28,0,0,0,91,0,0,0,1,2,88,70,1,0,0,0,28,0,0,0,0,1,0,32,88,0,0,0,48,0,0,0,2,0,0,0,1,0,0,0,56,0,0,0,72,0,0,0,67,111,108,111,114,0,171,171,1,0,3,0,1,0,3,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,116,120,0,77,105,99,114,111,115,111,102,116,32,40,82,41,32,72,76,83,76,32,83,104,97,100,101,114,32,67,111,109,112,105,108,101,114,32,57,46,50,54,46,57,53,50,46,50,56,52,52,0,254,255,12,0,80,82,83,73,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,254,255,18,0,67,76,73,84,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,255,20,0,70,88,76,67,2,0,0,0,3,0,0,16,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,1,0,0,16,1,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0,240,240,240,240,15,15,15,15,255,255,0,0,1,0,0,2,0,8,15,128,0,0,228,160,255,255,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,212,1,0,0,0,2,254,255,254,255,63,0,67,84,65,66,28,0,0,0,198,0,0,0,0,2,254,255,3,0,0,0,28,0,0,0,0,0,0,32,191,0,0,0,88,0,0,0,2,0,8,0,4,0,0,0,100,0,0,0,116,0,0,0,180,0,0,0,2,0,4,0,4,0,0,0,100,0,0,0,116,0,0,0,185,0,0,0,2,0,0,0,4,0,0,0,100,0,0,0,116,0,0,0,80,114,111,106,101,99,116,105,111,110,0,171,3,0,3,0,4,0,4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,86,105,101,119,0,87,111,114,108,100,0,118,115,95,50,95,48,0,77,105,99,114,111,115,111,102,116,32,40,82,41,32,72,76,83,76,32,83,104,97,100,101,114,32,67,111,109,112,105,108,101,114,32,57,46,50,54,46,57,53,50,46,50,56,52,52,0,171,31,0,0,2,0,0,0,128,0,0,15,144,9,0,0,3,0,0,1,128,0,0,228,144,0,0,228,160,9,0,0,3,0,0,2,128,0,0,228,144,1,0,228,160,9,0,0,3,0,0,4,128,0,0,228,144,2,0,228,160,9,0,0,3,0,0,8,128,0,0,228,144,3,0,228,160,9,0,0,3,1,0,1,128,0,0,228,128,4,0,228,160,9,0,0,3,1,0,2,128,0,0,228,128,5,0,228,160,9,0,0,3,1,0,4,128,0,0,228,128,6,0,228,160,9,0,0,3,1,0,8,128,0,0,228,128,7,0,228,160,9,0,0,3,0,0,1,192,1,0,228,128,8,0,228,160,9,0,0,3,0,0,2,192,1,0,228,128,9,0,228,160,9,0,0,3,0,0,4,192,1,0,228,128,10,0,228,160,9,0,0,3,0,0,8,192,1,0,228,128,11,0,228,160,255,255,0,0 };
#endif
#if XBOX
        private Byte[] pickingEffectCode = new Byte[1380] { 188, 240, 11, 207, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 254, 255, 9, 1, 0, 0, 1, 192, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 87, 111, 114, 108, 100, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 86, 105, 101, 119, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 1, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 80, 114, 111, 106, 101, 99, 116, 105, 111, 110, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 1, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 67, 111, 108, 111, 114, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 80, 97, 115, 115, 49, 0, 0, 0, 0, 0, 0, 11, 84, 101, 99, 104, 110, 105, 113, 117, 101, 49, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 64, 0, 0, 1, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 176, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 164, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 1, 120, 0, 0, 1, 116, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 1, 144, 0, 0, 1, 140, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 216, 16, 42, 17, 0, 0, 0, 0, 180, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 28, 0, 0, 0, 95, 255, 255, 3, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 48, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 56, 0, 0, 0, 72, 67, 111, 108, 111, 114, 0, 171, 171, 0, 1, 0, 3, 0, 1, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 115, 95, 51, 95, 48, 0, 50, 46, 48, 46, 49, 49, 54, 50, 54, 46, 48, 0, 171, 0, 0, 0, 0, 0, 0, 0, 36, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 16, 1, 196, 0, 34, 0, 0, 0, 200, 143, 192, 0, 0, 192, 192, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 244, 16, 42, 17, 1, 0, 0, 1, 40, 0, 0, 0, 204, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 28, 0, 0, 0, 198, 255, 254, 3, 0, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 191, 0, 0, 0, 88, 0, 2, 0, 8, 0, 4, 0, 0, 0, 0, 0, 100, 0, 0, 0, 116, 0, 0, 0, 180, 0, 2, 0, 4, 0, 4, 0, 0, 0, 0, 0, 100, 0, 0, 0, 116, 0, 0, 0, 185, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 100, 0, 0, 0, 116, 80, 114, 111, 106, 101, 99, 116, 105, 111, 110, 0, 171, 0, 3, 0, 3, 0, 4, 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 105, 101, 119, 0, 87, 111, 114, 108, 100, 0, 118, 115, 95, 51, 95, 48, 0, 50, 46, 48, 46, 49, 49, 54, 50, 54, 46, 48, 0, 171, 171, 0, 0, 0, 0, 0, 0, 0, 204, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 144, 0, 0, 0, 3, 16, 1, 16, 3, 0, 0, 18, 0, 194, 0, 0, 0, 0, 0, 96, 4, 96, 10, 18, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 3, 196, 0, 34, 0, 0, 0, 5, 248, 0, 0, 0, 0, 6, 136, 0, 0, 0, 0, 200, 1, 0, 1, 0, 167, 167, 0, 175, 0, 0, 0, 200, 2, 0, 1, 0, 167, 167, 0, 175, 0, 1, 0, 200, 4, 0, 1, 0, 167, 167, 0, 175, 0, 2, 0, 200, 8, 0, 1, 0, 167, 167, 0, 175, 0, 3, 0, 200, 1, 0, 0, 0, 167, 167, 0, 175, 1, 4, 0, 200, 2, 0, 0, 0, 167, 167, 0, 175, 1, 5, 0, 200, 4, 0, 0, 0, 167, 167, 0, 175, 1, 6, 0, 200, 8, 0, 0, 0, 167, 167, 0, 175, 1, 7, 0, 200, 1, 128, 62, 0, 167, 167, 0, 175, 0, 8, 0, 200, 2, 128, 62, 0, 167, 167, 0, 175, 0, 9, 0, 200, 4, 128, 62, 0, 167, 167, 0, 175, 0, 10, 0, 200, 8, 128, 62, 0, 167, 167, 0, 175, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#endif
        #endregion

        private Effect PickingEffect;

        public RenderTarget2D RenderTarget;
        public RenderTarget2D PickerTarget;

        private SpriteBatch batch;

        BrainModel Cylinder;
        BrainModel Cone;
        BrainModel Plane;

        Vector3 CurrentPosition;

        ShapeDrawer ShapeDrawer;

        private Line3D XLine;
        private Line3D YLine;
        private Line3D ZLine;

        private Line3D XYLine1;
        private Line3D XYLine2;

        private Line3D YZLine1;
        private Line3D YZLine2;

        private Line3D XZLine1;
        private Line3D XZLine2;

        public PickingManager3D_Color()
        {
            ShapeDrawer = new ShapeDrawer();

           

            Cylinder = ModelUtil.GenerateCylinderMesh(5, 1, 16);
            Cone = ModelUtil.GenerateConeMesh(2, 1.5f, 0, 16);
            Plane = ModelUtil.GeneratePlaneMesh(1f);

            batch = new SpriteBatch(Engine.Instance.GraphicsDevice);

            int size = 512;
            RenderTarget = new RenderTarget2D(Engine.Instance.GraphicsDevice, size, size,
                false, SurfaceFormat.Color, DepthFormat.Depth24);

            PresentationParameters pp = Engine.Instance.GraphicsDevice.PresentationParameters;
            PickerTarget = new RenderTarget2D(Engine.Instance.GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight,
                false, SurfaceFormat.Color, DepthFormat.Depth24);

#if MONOGAME

#else
            PickingEffect = new Effect(Engine.Instance.GraphicsDevice, pickingEffectCode);
#endif

            ShouldUpdate = true;
            ShouldDraw = true;
        }

        public void Update()
        {



        }

        private void DrawBrainModel(BrainModel model)
        {
            GraphicsDevice device = Engine.Instance.GraphicsDevice;
            foreach (BrainModelMesh mesh in model.Meshes)
            {
                if (mesh.IndexBuffer != null &&
                    mesh.IndexBuffer.IsDisposed ||
                    mesh.VertexBuffer.IsDisposed)
                {
                    return;
                }

                device.Indices = mesh.IndexBuffer;
                device.SetVertexBuffer(mesh.VertexBuffer);

                int count = this.PickingEffect.CurrentTechnique.Passes.Count;

                for (int p = 0; p < count; p++)
                {
                    PickingEffect.CurrentTechnique.Passes[p].Apply();

                    if (mesh.IndexBuffer == null)
                        device.DrawPrimitives(PrimitiveType.TriangleList, 0, mesh.PrimitiveCount);
                    else
                        device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0,
                            mesh.NumVertices, mesh.VertexOffset, mesh.PrimitiveCount);
                }
            }
        }
        private void DrawModel(Model model)
        {
            GraphicsDevice device = Engine.Instance.GraphicsDevice;
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    if (part.IndexBuffer != null &&
                        part.IndexBuffer.IsDisposed ||
                        part.VertexBuffer.IsDisposed)
                    {
                        return;
                    }

                    device.Indices = part.IndexBuffer;
                    device.SetVertexBuffer(part.VertexBuffer);

                    int count = this.PickingEffect.CurrentTechnique.Passes.Count;

                    for (int p = 0; p < count; p++)
                    {
                        PickingEffect.CurrentTechnique.Passes[p].Apply();

                        if (part.IndexBuffer == null)
                            device.DrawPrimitives(PrimitiveType.TriangleList, 0, part.PrimitiveCount);
                        else
                            device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0,
                                part.NumVertices, part.VertexOffset, part.PrimitiveCount);
                    }
                }
            }
        }

        float Terrain_Strength = 1;
        public Vector3 WorldPosition;
        public bool BlockInput;

        public void Draw()
        {
            if (Engine.Instance.RenderManager3D == null)
            {
                return;
            }

            ICamera3D camera = Engine.Instance.CameraManager.Camera3D;
            if (camera == null)
            {
                return;
            }
            
            GraphicsDevice device = Engine.Instance.GraphicsDevice;

            Vector2 mousePos = Engine.Instance.InputManager.GetMousePosition();
            int X = (int)mousePos.X;
            int Y = (int)mousePos.Y;

            if (Helper != null)
            {
                Helper.Update(X, Y, Engine.Instance.InputManager.IsMouseLeftDown(), Terrain_Strength);
                Helper.Draw();
            }

            IPickedObject wo_Mani = null;
            if (!Manipulating)
            {
                wo_Mani = Pick(X, Y, device.Viewport, camera, out UnitAxis);
                if (!BlockInput && Engine.Instance.InputManager.IsMouseLeftClick())
                {
                    if (wo_Mani != null &&
                        wo_Mani != this.SelectedWorldObject)
                    {
                        this.SelectedWorldObject = wo_Mani;
                        WorldPosition = wo_Mani.Position;
                        if (OnSelected != null)
                            OnSelected(wo_Mani);
                    }
                }
            }

            Vector3 Position = Vector3.Zero;
            float size = 15;
            RelativeScale = 5;
            if (this.SelectedWorldObject != null)
            {
                Position = SelectedWorldObject.Position;

                // Here, we calculate the Scale of the 3D Picker,
                // so it will always be of the same size,
                // doesn't matter the distance the user is from it
                if (!Manipulating)
                {
                    Vector3 viewPosition = camera.Position;

                    Matrix ScaleView = Matrix.CreateLookAt(Vector3.UnitZ *
                        Vector3.Distance(viewPosition, Position), Vector3.Zero, Vector3.Up);

                    Vector3 ProjStart = Engine.Instance.GraphicsDevice.Viewport.Project(
                        Vector3.Zero, camera.Projection, ScaleView, Matrix.Identity);
                    Vector3 ProjEnd = Engine.Instance.GraphicsDevice.Viewport.Project(
                        Vector3.UnitX, camera.Projection, ScaleView, Matrix.Identity);

                    RelativeScale = size / (ProjEnd - ProjStart).Length();

                    ScaleBefore = RelativeScale;
                }
                else
                {
                    RelativeScale = ScaleBefore;
                }

                if (Engine.Instance.InputManager.IsMouseLeftDown() && !BlockInput)
                {
                    Manipulating = true;

                    if (UnitAxis != Vector3.Zero)
                    {
                        if (UnitAxis.X != 0)
                        {
                            ApplyAxis(new Vector3(UnitAxis.X, 0, 0), camera);
                        }
                        if (UnitAxis.Y != 0)
                        {
                            ApplyAxis(new Vector3(0, UnitAxis.Y, 0), camera);
                        }
                        if (UnitAxis.Z != 0)
                        {
                            ApplyAxis(new Vector3(0, 0, UnitAxis.Z), camera);
                        }
                    }
                }
                else
                {
                    Manipulating = false;
                }
            }

            CurrentPosition = Position;

            device.SetRenderTarget(this.RenderTarget);
            device.Clear(Color.Transparent);
            IRenderManager3D renderManager = Engine.Instance.RenderManager3D;
            ICamera3D Camera = Engine.Instance.CameraManager.Camera3D;
            PickingEffect.Parameters["View"].SetValue(Camera.View);
            PickingEffect.Parameters["Projection"].SetValue(Camera.Projection);
            for (int i = 0; i < renderManager.Editor_Count(); i++)
            {
                IWorldObject wo = renderManager.Editor_GetWorldObject(i);

                PickingEffect.Parameters["World"].SetValue(wo.WorldMatrix);
                PickingEffect.Parameters["Color"].SetValue(GetColor(wo).ToVector3());
                if (wo.RenderingTag is BrainModel)
                {
                    BrainModel model = wo.RenderingTag as BrainModel;
                    DrawBrainModel(model);
                }
                if (wo.Model is BrainModel)
                {
                    BrainModel model = wo.Model as BrainModel;
                    DrawBrainModel(model);
                }
                if (wo.Model is Model)
                {
                    Model model = wo.Model as Model;
                    DrawModel(model);
                }
            }
            device.SetRenderTarget(null);

            device.SetRenderTarget(PickerTarget);
            device.Clear(Color.Transparent);

            if (SelectedWorldObject != null)
            {
                device.DepthStencilState = DepthStencilState.Default;
                ScaleMatrix = Matrix.CreateScale(RelativeScale);

                switch (Mode)
                {
                    case ManipulationMode3D.Translation:
                        {
                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 0, 2.5f * RelativeScale)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 0, 1));
                            DrawBrainModel(this.Cylinder);
                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 0, 5 * RelativeScale) + new Vector3(0, 0, 0.5f * RelativeScale)));
                            DrawBrainModel(this.Cone);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 2.5f * RelativeScale, 0)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 1, 0));
                            DrawBrainModel(this.Cylinder);
                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 5 * RelativeScale, 0) + new Vector3(0, 0.5f * RelativeScale, 0)));
                            DrawBrainModel(this.Cone);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationZ(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition - new Vector3(2.5f * RelativeScale, 0, 0)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 0, 0));
                            DrawBrainModel(this.Cylinder);
                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationZ(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition - new Vector3(5 * RelativeScale, 0, 0) - new Vector3(0.5f * RelativeScale, 0, 0)));
                            DrawBrainModel(this.Cone);

                            if (Grid == 0)
                            {
                                Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
                                PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateTranslation(CurrentPosition + new Vector3(-RelativeScale * 1.5f, RelativeScale * 1.5f, 0)));
                                PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 1, 0));
                                DrawBrainModel(Plane);

                                PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationY(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, RelativeScale * 1.5f, RelativeScale * 1.5f)));
                                PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 1, 1));
                                DrawBrainModel(Plane);

                                PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(-RelativeScale * 1.5f, 0, RelativeScale * 1.5f)));
                                PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 0, 1));
                                DrawBrainModel(Plane);
                                Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
                            }
                        }
                        break;
                    case ManipulationMode3D.Rotation:
                        {
                            float Relative2 = RelativeScale * 2;
                            float RelativeD5 = RelativeScale / 5;
                            Matrix scale = Matrix.CreateScale(Relative2, RelativeD5, Relative2);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 0, 2.5f * RelativeScale)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 0, 1));
                            DrawBrainModel(this.Cylinder);
                            PickingEffect.Parameters["World"].SetValue(scale * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 0, 5 * RelativeScale)));
                            DrawBrainModel(this.Cylinder);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 2.5f * RelativeScale, 0)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 1, 0));
                            DrawBrainModel(this.Cylinder);
                            PickingEffect.Parameters["World"].SetValue(scale * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 5 * RelativeScale, 0)));
                            DrawBrainModel(this.Cylinder);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationZ(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition - new Vector3(2.5f * RelativeScale, 0, 0)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 0, 0));
                            DrawBrainModel(this.Cylinder);
                            PickingEffect.Parameters["World"].SetValue(scale * Matrix.CreateRotationZ(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition - new Vector3(5 * RelativeScale, 0, 0)));
                            DrawBrainModel(this.Cylinder);
                        }
                        break;
                    case ManipulationMode3D.Scale:
                        {
                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 0, 2.5f * RelativeScale)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 0, 1));
                            DrawBrainModel(this.Cylinder);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 2.5f * RelativeScale, 0)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 1, 0));
                            DrawBrainModel(this.Cylinder);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationZ(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition - new Vector3(2.5f * RelativeScale, 0, 0)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 0, 0));
                            DrawBrainModel(this.Cylinder);

                            Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullClockwise;
                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateBillboard(CurrentPosition + new Vector3(RelativeScale * -5f, 0, 0), camera.Position, camera.Up, null));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 0, 0));
                            DrawBrainModel(Plane);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateBillboard(CurrentPosition + new Vector3(0, RelativeScale * 5f, 0), camera.Position, camera.Up, null));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 1, 0));
                            DrawBrainModel(Plane);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateBillboard(CurrentPosition + new Vector3(0, 0, RelativeScale * 5f), camera.Position, camera.Up, null));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 0, 1));
                            DrawBrainModel(Plane);
                            Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
                            break;
                        }
                }
            }

            device.SetRenderTarget(null);
        }

        float increase = 0;
        private void ApplyAxis(Vector3 axis, ICamera3D Camera)
        {
            Matrix Translation = Matrix.Identity;
            Matrix Projection = Camera.Projection;
            Matrix View = Camera.View;
            Viewport Viewport = Engine.Instance.GraphicsDevice.Viewport;
            Vector2 Delta = Engine.Instance.InputManager.GetMouseDifference();
            if (Delta != Vector2.Zero)
            {
                Vector3 StartPosition = Viewport.Project(Vector3.Zero, Projection, View, Translation);
                Vector3 EndPosition = Viewport.Project(axis, Projection, View, Translation);

                Vector3 ScreenDirection = Vector3.Normalize(EndPosition - StartPosition);
                float delta = Delta.X + Delta.Y;

                if (Mode == ManipulationMode3D.Translation)
                {
                    EndPosition = StartPosition + (ScreenDirection * (Vector3.Dot(new Vector3(Delta, 0f), ScreenDirection)));
                }
                else
                {
                    EndPosition = StartPosition + (ScreenDirection * (Vector3.Dot(new Vector3(delta, delta, 0f), ScreenDirection)));
                }

                StartPosition = Viewport.Unproject(StartPosition, Projection, View, Translation);
                EndPosition = Viewport.Unproject(EndPosition, Projection, View, Translation);

                Vector3 Difference = EndPosition - StartPosition;
                float sum = Math.Abs(Vector3Util.Sum(Difference));
                increase += sum;

                if (increase > Grid)
                {
                    increase = 0;
                    float multi = delta > 0 ? 1 : -1;

                    switch (Mode)
                    {
                        case ManipulationMode3D.Translation:

                            if (Grid != 0)
                            {
                                Vector3 add =  (UnitAxis * new Vector3(Grid) * multi);
                                add.Y = -add.Y;
                                Vector3 pos = SelectedWorldObject.Position +add;
                                pos.X = MathUtil.NextMultiple((int)pos.X, Grid);
                                pos.Y = MathUtil.NextMultiple((int)pos.Y, Grid);
                                pos.Z = MathUtil.NextMultiple((int)pos.Z, Grid);
                                SelectedWorldObject.Position = pos;
                            }
                            else
                            {
                                SelectedWorldObject.Position += Difference;
                            }

                            WorldPosition = SelectedWorldObject.Position;
                            break;
                        case ManipulationMode3D.Scale:
                            {
                                float min = 0.1f;

                                if (Grid != 0)
                                {
                                    Vector3 add = (UnitAxis * new Vector3(Grid) * multi);
                                    add.Y = -add.Y;
                                    add.X = -add.X;
                                    Vector3 sca = SelectedWorldObject.Scale + add;
                                    sca.X = MathUtil.NextMultiple((int)sca.X, Grid);
                                    sca.Y = MathUtil.NextMultiple((int)sca.Y, Grid);
                                    sca.Z = MathUtil.NextMultiple((int)sca.Z, Grid);
                                    SelectedWorldObject.Scale = Vector3Util.Min(sca, new Vector3(min));
                                }
                                else
                                {
                                    SelectedWorldObject.Scale += Difference;
                                    SelectedWorldObject.Scale = Vector3Util.Min(SelectedWorldObject.Scale, new Vector3(min));
                                }
                            }
                            break;
                        case ManipulationMode3D.UniformScale:
                            {
                                float min = 0.1f;
                                SelectedWorldObject.Scale = Vector3Util.Min(SelectedWorldObject.Scale + new Vector3(Vector3Util.Average(Difference)), new Vector3(min));
                            }
                            break;
                        case ManipulationMode3D.Rotation:
                            {
                                if (Grid != 0)
                                {
                                    Vector3 add = Vector3Util.ToRadians((UnitAxis * new Vector3(Grid) * multi));
                                    add.Y = -add.Y;
                                    Vector3 rot = SelectedWorldObject.RotationRadians + add;
                                    SelectedWorldObject.RotationRadians = rot;
                                }
                                else
                                {
                                    SelectedWorldObject.RotationRadians += Difference;
                                }
                            }
                            break;

                    }
                }
            }
        }

        private Matrix ScaleMatrix;
        float RelativeScale;

        public void EndDraw()
        {
            /*batch.Begin();
            batch.Draw(this.PickerTarget, Engine.Instance.GraphicsDevice.Viewport.Bounds, Color.White);
            batch.End();*/

            ICamera3D Camera = Engine.Instance.CameraManager.Camera3D;
            if (Camera != null)
            {
                Engine.Instance.GraphicsDevice.DepthStencilState = DepthStencilState.None;

                float Two = 2.5f * RelativeScale;
                float Five = 5f * RelativeScale;

                XLine = new Line3D(CurrentPosition, CurrentPosition - new Vector3(Five, 0, 0), new Color(255, 0, 0));
                YLine = new Line3D(CurrentPosition, CurrentPosition + new Vector3(0, Five, 0), new Color(0, 255, 0));
                ZLine = new Line3D(CurrentPosition, CurrentPosition + new Vector3(0, 0, Five), new Color(0, 0, 255));               

                PickingEffect.Parameters["View"].SetValue(Camera.View);
                PickingEffect.Parameters["Projection"].SetValue(Camera.Projection);

                switch (Mode)
                {
                    case ManipulationMode3D.Translation:
                        {
                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 0, Five) + new Vector3(0, 0, 0.5f * RelativeScale)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 0, 1));
                            DrawBrainModel(this.Cone);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, Five, 0) + new Vector3(0, 0.5f * RelativeScale, 0)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 1, 0));
                            DrawBrainModel(this.Cone);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationZ(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition - new Vector3(5 * RelativeScale, 0, 0) - new Vector3(0.5f * RelativeScale, 0, 0)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 0, 0));
                            DrawBrainModel(this.Cone);

                            XYLine1 = new Line3D(XLine.Start + new Vector3(-Two, Two, 0), XLine.Start + new Vector3(0, Two, 0), YLine.Color);
                            XYLine2 = new Line3D(XLine.Start + new Vector3(-Two, Two, 0), XLine.Start - new Vector3(Two, 0, 0), XLine.Color);

                            YZLine1 = new Line3D(ZLine.Start + new Vector3(0, Two, Two), XLine.Start + new Vector3(0, Two, 0), YLine.Color);
                            YZLine2 = new Line3D(ZLine.Start + new Vector3(0, Two, Two), XLine.Start + new Vector3(0, 0, Two), ZLine.Color);

                            XZLine1 = new Line3D(XLine.Start - new Vector3(Two, 0, 0), XLine.Start + new Vector3(-Two, 0, Two), XLine.Color);
                            XZLine2 = new Line3D(ZLine.Start + new Vector3(0, 0, Two), XLine.Start + new Vector3(-Two, 0, Two), ZLine.Color);

                            if (UnitAxis != Vector3.Zero)
                            {
                                if (UnitAxis.X == 1 && UnitAxis.Y == 1)
                                {
                                    XYLine1.Color = Color.Yellow;
                                    XYLine2.Color = Color.Yellow;

                                    Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
                                    PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateTranslation(CurrentPosition + new Vector3(-RelativeScale * 1.5f, RelativeScale * 1.5f, 0)));
                                    PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 1, 0));
                                    DrawBrainModel(Plane);
                                    Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
                                }
                                else if (UnitAxis.Y == 1 && UnitAxis.Z == 1)
                                {
                                    YZLine1.Color = Color.Yellow;
                                    YZLine2.Color = Color.Yellow;

                                    Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
                                    PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationY(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, RelativeScale * 1.5f, RelativeScale * 1.5f)));
                                    PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 1, 0));
                                    DrawBrainModel(Plane);
                                    Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
                                }
                                else if (UnitAxis.X == 1 && UnitAxis.Z == 1)
                                {
                                    XZLine1.Color = Color.Yellow;
                                    XZLine2.Color = Color.Yellow;

                                    Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
                                    PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(-RelativeScale * 1.5f, 0, RelativeScale * 1.5f)));
                                    PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 1, 0));
                                    DrawBrainModel(Plane);
                                    Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
                                }
                                else if (UnitAxis.X == 1)
                                {
                                    XLine.Color = Color.Yellow;
                                }
                                else if (UnitAxis.Y == 1)
                                {
                                    YLine.Color = Color.Yellow;
                                }
                                else if (UnitAxis.Z == 1)
                                {
                                    ZLine.Color = Color.Yellow;
                                }
                            }

                            ShapeDrawer.Submit(XLine);
                            ShapeDrawer.Submit(YLine);
                            ShapeDrawer.Submit(ZLine);

                            if (Grid == 0)
                            {
                                ShapeDrawer.Submit(XYLine1);
                                ShapeDrawer.Submit(XYLine2);
                                ShapeDrawer.Submit(YZLine1);
                                ShapeDrawer.Submit(YZLine2);
                                ShapeDrawer.Submit(XZLine1);
                                ShapeDrawer.Submit(XZLine2);
                            }
                        }
                        break;
                    case ManipulationMode3D.Rotation:
                        {
                            float Relative2 = RelativeScale * 2;
                            float RelativeD5 = RelativeScale / 5;
                            Matrix scale = Matrix.CreateScale(Relative2, RelativeD5, Relative2);

                            PickingEffect.Parameters["World"].SetValue(scale * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 0, 5 * RelativeScale) + new Vector3(0, 0, 0.5f * RelativeScale)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 0, 1));
                            DrawBrainModel(this.Cylinder);

                            PickingEffect.Parameters["World"].SetValue(scale * Matrix.CreateTranslation(CurrentPosition + new Vector3(0, 5 * RelativeScale, 0) + new Vector3(0, 0.5f * RelativeScale, 0)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 1, 0));
                            DrawBrainModel(this.Cylinder);

                            PickingEffect.Parameters["World"].SetValue(scale * Matrix.CreateRotationZ(MathHelper.PiOver2) * Matrix.CreateTranslation(CurrentPosition - new Vector3(5 * RelativeScale, 0, 0) - new Vector3(0.5f * RelativeScale, 0, 0)));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 0, 0));
                            DrawBrainModel(this.Cylinder);

                            if (UnitAxis != Vector3.Zero)
                            {
                                if (UnitAxis.X == 1)
                                {
                                    XLine.Color = Color.Yellow;
                                }
                                else if (UnitAxis.Y == 1)
                                {
                                    YLine.Color = Color.Yellow;
                                }
                                else if (UnitAxis.Z == 1)
                                {
                                    ZLine.Color = Color.Yellow;
                                }
                            }

                            ShapeDrawer.Submit(XLine);
                            ShapeDrawer.Submit(YLine);
                            ShapeDrawer.Submit(ZLine);
                        }
                        break;
                    case ManipulationMode3D.Scale:
                        {
                            Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullClockwise;
                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateBillboard(CurrentPosition + new Vector3(RelativeScale * -5f, 0, 0), Camera.Position, Camera.Up, null));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(1, 0, 0));
                            DrawBrainModel(Plane);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateBillboard(CurrentPosition + new Vector3(0, RelativeScale * 5f, 0), Camera.Position, Camera.Up, null));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 1, 0));
                            DrawBrainModel(Plane);

                            PickingEffect.Parameters["World"].SetValue(ScaleMatrix * Matrix.CreateBillboard(CurrentPosition + new Vector3(0, 0, RelativeScale * 5f), Camera.Position, Camera.Up, null));
                            PickingEffect.Parameters["Color"].SetValue(new Vector3(0, 0, 1));
                            DrawBrainModel(Plane);
                            Engine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;

                            if (UnitAxis != Vector3.Zero)
                            {
                                if (UnitAxis.X == 1)
                                {
                                    XLine.Color = Color.Yellow;
                                }
                                else if (UnitAxis.Y == 1)
                                {
                                    YLine.Color = Color.Yellow;
                                }
                                else if (UnitAxis.Z == 1)
                                {
                                    ZLine.Color = Color.Yellow;
                                }
                            }

                            ShapeDrawer.Submit(XLine);
                            ShapeDrawer.Submit(YLine);
                            ShapeDrawer.Submit(ZLine);
                        }
                        break;
                }

                ShapeDrawer.DrawEverything(Camera);

                Engine.Instance.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            }
        }


        public IPickedObject Pick(int X, int Y, Viewport viewport, ICamera3D Camera, out Vector3 Axis)
        {
            IRenderManager3D renderManager = Engine.Instance.RenderManager3D;

            GraphicsDevice device= Engine.Instance.GraphicsDevice;
            Viewport view = device.Viewport;
            float xRatio = (float)this.RenderTarget.Width / (float)view.Width;
            float yRatio = (float)this.RenderTarget.Height / (float)view.Height;

            int x = IntUtil.Clamp((int)(X * xRatio), 0, RenderTarget.Width - 1);
            int y = IntUtil.Clamp((int)(Y * yRatio), 0, RenderTarget.Height - 1);
            Rectangle rect = new Rectangle(x, y, 1, 1);
            Color[] data = new Color[1];
            this.RenderTarget.GetData(0, rect, data, 0, 1);

            float xRatio2 = (float)this.PickerTarget.Width / (float)view.Width;
            float yRatio2 = (float)this.PickerTarget.Height / (float)view.Height;
            int x2 = IntUtil.Clamp((int)(X * xRatio2), 0, PickerTarget.Width - 1);
            int y2 = IntUtil.Clamp((int)(Y * yRatio2), 0, PickerTarget.Height - 1);
            Rectangle rect2 = new Rectangle(x2, y2, 1, 1);
            Color[] data2 = new Color[1];
            this.PickerTarget.GetData(0, rect2, data2, 0, 1);

            Color color = data[0];
            Color pickerColor = data2[0];
            Axis = Vector3.Zero;
            if (pickerColor == Color.Transparent)
            {
                for (int i = 0; i < renderManager.Editor_Count(); i++)
                {
                    IWorldObject wo = renderManager.Editor_GetWorldObject(i);

                    if (color == GetColor(wo))
                    {
                        Axis = Vector3.Zero;
                        return wo;
                    }
                }
            }

            Axis = pickerColor.ToVector3();

            return null;
        }

        public Color GetColor(IWorldObject wo)
        {
            if (wo.PickingTag == null)
            {
                if (LastPickColor.B < 255)
                {
                    LastPickColor.B++;
                }
                else
                {
                    if (LastPickColor.G < 255)
                    {
                        LastPickColor.G++;
                        LastPickColor.B = 0;
                    }
                    else
                    {
                        if (LastPickColor.R < 255)
                        {
                            LastPickColor.R++;
                            LastPickColor.G = 0;
                        }
                    }
                }

                wo.PickingTag = new Color(LastPickColor.R, LastPickColor.G,
                        LastPickColor.B);
            }
            Color c = (Color)wo.PickingTag;
            return c;
        }
        public TerrainEditorHelper Helper;
        public void EnableTerrainEditting()
        {
            if (this.SelectedWorldObject is TerrainWorldObject)
            {
                if (Helper != null)
                {
                    Helper.Dispose();
                }
                Helper = new TerrainEditorHelper(this.SelectedWorldObject as TerrainWorldObject);
            }
        }


        public void SetTerrainEdittingStrength(float strength)
        {
            this.Terrain_Strength = strength;
        }

        public void SetTerrainEdittingSize(float size)
        {
            if (this.Helper != null)
            {
                this.Helper.PickerSize = size;
            }
        }

        private int gridIncresae = 1;
        public void LessGrid()
        {
            Grid -= gridIncresae;
            Grid = IntUtil.Clamp(Grid, 0, 256);
        }

        public void MoreGrid()
        {
            Grid += gridIncresae;
            Grid = IntUtil.Clamp(Grid, 0, 256);
        }
    }
#endif
}
